<#macro search_table_demo>
				      
<div data-bind='component: {name: "search-table", params:{
		title:"Search By"
		,dataUrlSearch:"/expense/all" 
		,allowSearch:true
		,fields:[
			{name:"description",header:"Title",type:"text", readonly:true}, 
			{name:"expenseId",header:"Expense No.",type:"text", readonly:true, searchable:true}, 			
			<#-- {name:"status",header:"Status",type:"select",options:[{value:"0",label:"Draft"},{value:"1",label:"Pending"}], readonly:true, searchable:true},-->
			{name:"status",header:"Status",type:"text", readonly:true},	
			{name:"staffId",header:"Staff No.",type:"text", readonly:true, searchable:true},		
			{name:"extensionNo",header:"Extension No.",type:"text", readonly:true},
			{name:"nextApprover",header:"Next Approver",type:"text", readonly:true},
			{name:"lastApprover",header:"Last Approver",type:"text", readonly:true},
			<#-- {name:"siteId",header:"Site",type:"select",options:[{value:"0",label:"Guangzhou"},{value:"1",label:"XiAn"}], readonly:true},-->
			{name:"siteId",header:"Site",type:"text", readonly:true},
			{name:"submittedDate",header:"Submision Date",type:"date", readonly:true, searchable:true},
			{name:"confirmedDate",header:"Confirm Date",type:"date", readonly:true},			
			{name:"clarityProjectId",header:"Project ID",type:"text", readonly:true, searchable:true},
			{name:"clarityProjectName",header:"Project Name",type:"text", readonly:true},
			{name:"customerCostCentreName",header:"Cost Center Name",type:"text", readonly:true},
			{name:"customerCostCentreNo",header:"Cost Center No.",type:"text", readonly:true},
			{name:"customerCostCentreMandatory",header:"Cost Center Mandatory",type:"text", readonly:true},
			{name:"billable",header:"Billable",type:"text", readonly:true},
			{name:"totalAmount",header:"Total Amount",type:"text", readonly:true},
			{name:"expenseCashAdvanceAmount",header:"Cash Advance",type:"text", readonly:true}
		]
		,limit:5
		,selector:false	
		,tableRowStyle: function(data){			
            return {"backgroundColor":{"0":"pink","1":"white"}[data.description?0:1]};
		} 
		
	}}'>
</div>

<script type="text/javascript">
	
	<@search_table/>
</script>
</#macro>

<#macro search_table_pagination>
	<#local template>
	<#compress>
	<div data-bind="with: parent">		
		总共<span data-bind="text:count"></span>条记录 &nbsp;
		每页显示
		<#-- <input data-bind="value: limit" style="width:5em"></input> -->
		<span data-bind="text: limit" style="width:5em"></span>
		条记录 &nbsp; 
		<!-- ko if: count() > limit() -->
		当前显示页&nbsp;
		<!-- ko foreach: $component.indecies -->
			<button class="btn btn-default" data-bind="text: $data, style: $component.style($data), clickBubble:false, click: $component.selectme"></button>			
		<!-- /ko -->			
		<!-- /ko -->
	</div>
	</#compress>
	</#local>
	ko.components.register("search-table-pagination",{
		template: "${template?js_string}"
		,viewModel: function(params){
			console.log("params====",params);
			this.parent = params.parent;
			<#-- 			
			this.page = params.page;
			this.limit = params.limit;
			this.count = params.count;
			this.search = params.searchRecord;
			-->
			this.indecies = ko.computed(function(){
				var indecies = [];				 
				for(var i = 1, size = this.parent.count() / this.parent.limit() + 1; i < size; i++){
					indecies.push(i);
				} 
				return indecies;
			}.bind(this));
			
			this.style = function(page){
				 
				if(page == this.parent.page()){
					return {color: 'red',fontWeight:'bold',fontSize:'large'};
				}
				
			    return {color: 'black',fontWeight:'normal',fontSize:'medium'};
			}.bind(this);
			
			this.selectme = function(page,event){
				this.parent.page(page);
				this.parent.searchRecord(this.parent);
			}.bind(this);
			<#-- 
			this.parent.limit.valueChanged(function(oldVal,newVal) {
				
			});
			-->
		}
	});
</#macro>	
<#-- reference documents -->
<#-- 
https://knockoutjs.com/documentation/options-binding.html
https://knockoutjs.com/documentation/foreach-binding.html 
http://www.bootcss.com/p/bootstrap-datetimepicker/
-->
<#macro search_table >
	<#local template>
	<#compress>
		<#-- search criteria -->
		<nav> 
			<div class="container-fluid"> 
				<div class="navbar-header"> 
					<a class="navbar-brand" href="#"  data-bind="text: title"></a> 
				</div>
				<form class="navbar-form navbar-left">					
					<select  class="search-field" data-bind="options: searchParamfields, optionsText: 'header', optionsValue:'name', value: searchField, optionsCaption: '选择...'"></select>
					
					<!-- ko foreach: fields -->					
		        		<!-- ko if: type == 'text' -->
		        			<input data-bind="attr:{name: name}, css:name, style:{width:'12em'},visible: $parent.searchField() == name, value:$parent.sample[name]"></input>
		        		<!-- /ko -->	        				        	
			        	<!-- ko if: type == 'date' -->
			        		 <input type="date" data-bind="attr:{name: name}, css:name,style:{width:'12em'}, visible: $parent.searchField() == name, value:$parent.sample[name]"></input>	
			        	<!-- /ko -->		        		
			        	<!-- ko if: type == 'select' -->
			        		<select data-bind="attr:{name: name}, css:name, style:{width:'12em'}, options: options, optionsText: 'label', optionsValue:'value', optionsCaption: '选择...', visible: $parent.searchField() == name, value:$parent.sample[name]"></select>
			        	<!-- /ko -->
		        	<!-- /ko -->
			        
			        <span>&nbsp;&nbsp;</span>
			        
			        <button type="button" class="btn btn-primary" data-bind="click: searchRecord, visible: allowSearch">Search</button>
			        <button type="button" class="btn btn-default navbar-btn" data-bind="click:createRecord, visible: allowCreate">Add</button>
			        <button type="button" class="btn btn-default navbar-btn" data-bind="click:saveRecord, visible: allowSave">Save</button>
			        <button type="button" class="btn btn-default navbar-btn" data-bind="click:deleteRecord, visible: allowDelete">Delete</button>
			        <span data-bind="visible: showMessage, text:message" style="color:red"></span>
		    	</form> 		    	
		</nav>
						 
		<table data-toggle="table" data-bind="attr:{id: tableId}" class="ko-table">
		    <thead>
		        <tr class="ko-table-header">
		        	<!-- ko if: selector -->
		        	<th class="selector">
		        		<input type="checkbox" id="_selectAllCheckbox" onclick="ko.dataFor(this)._selectedAll(this.checked)"></input>
		        		全选
		        	</th>
		        	<!-- /ko -->		        	
		        	<!-- ko foreach: fields -->
		        	<!-- ko ifnot: hidden --><th data-bind="text: header"></th><!-- /ko -->
		        	<!-- /ko -->
		        </tr> 
		    </thead>
		    <tbody data-bind="foreach: {data:records, as:'record', afterRender: tableRowStyle}">
		    	
			        <tr class="ko-table-row-create" data-bind="event:$component.tableRowEvent()">
			        	<!-- ko if: $component.selector -->
			        	<td class="selector"><input type="checkbox" data-bind="checked: _selected"/></td>
			        	<!-- /ko -->		        	
			            <!-- ko foreach: $component.fields -->
				        <td data-bind="visible: $data.hidden != true">
				        		<#-- ko if: name == "id" || $data.readonly == true || (record.id != undefined && $component.allowUpdate == false) -->
				        		<!-- ko ifnot: $component.editable($data,record,name) -->				        		
				        			<span data-bind="text: $component.format(name,record)"></span>
				        		<!-- /ko -->
				        		<#-- ko if: name != "id" && $data.readonly != true && ($component.allowUpdate == true && $data.readonly != false || ($component.allowCreate == true && record.id == undefined)) -->
				        		<!-- ko if: $component.editable($data,record,name) -->
				        		<!-- ko if: type == 'text' -->
				        			<input data-bind="value:record[name]"></input>
				        		<!-- /ko -->
					        	<!-- ko if: type == 'date' -->
					        		 <input type="date" data-bind="value:record[name]"></input>	
					        	<!-- /ko -->		        		
					        	<!-- ko if: type == 'select' -->
					        		<select data-bind="options: options, optionsText: 'label', optionsValue:'value', value:record[name]"></select>
					        	<!-- /ko -->
					        	<!-- /ko -->
					    </td>    	
				        <!-- /ko -->
			        </tr>
		       	        	
		    </tbody>
		</table>
		
		<!-- ko if: $data.limit() > 0 -->
		<div data-bind='component: {name: "search-table-pagination", params:{parent:$data}}'></div>
		<!-- /ko -->
		<#-- 
		<table data-toggle="table" id="notice-home" data-url="/notice-home.json">
		    <thead>
		        <tr>
		          <th data-field="id">编号</th>
			      <th data-field="title">标题</th>
			      <th data-field="issuer">发文单位</th>
			      <th data-field="issueDate">发文日期</th>
			      <th data-field="status">状态</th>
			      <th data-field="deadline">截止日期</th>
		        </tr>
		    </thead>
		</table>
		-->
	</#compress>	
	</#local>
	ko.components.register("search-table",{
		template: "${template?js_string}"
		,viewModel: function(params){	
			<#-- ***** search criteria ***** -->
			this.searchField = ko.observable();
			this.fields = params.fields;	
			this.records = ko.observableArray().extend({deferred:true});		
			this.tableId = "tbl" + (""+Math.random()).substring(2);
			this.selector = params.selector;
			this.title = params.title?params.title:"[标题]";
			this.allowSearch = params.allowSearch?true:false
			this.allowCreate = params.allowCreate?true:false;
			this.allowDelete = params.allowDelete?true:false; 					
			this.allowUpdate = params.allowUpdate?true:false; 
			if(this.allowDelete || this.allowUpdate){
				this.selector = true;
			}
			this.allowSave =  params.allowSave?true:false; 
				
			this.showMessage = ko.observable(false);
			this.message = ko.observable();		
			
			this.page = ko.observable(params.page?params.page: 1);
			this.limit = ko.observable(params.limit?params.limit:0);
			this.count = ko.observable(0);
			 			
			this.editable = function(field,data,name) {
			    var readonly = (field.name == "id" || field.readonly == true || (data.id != undefined && this.allowUpdate == false));
			    <#-- 
			    var editable = true;
			    if(field.name == "id"  || field.readonly == true){
			    	editable = false;
			    } 
			    
			    if(data.id == undefined && field.readonly == true){
			    	editable = true;
			    }
			     -->
			    <#--			    
			    if(data.status == "A" && name == "title"){
			    	readonly = true;
			    } 
			    if(data.status == "B"){
			    	readonly = true;
			    }
			     -->
			    return !readonly;
			}.bind(this);
 			
			this.sample = {};
			this.searchParamfields = ko.observableArray().extend({deferred:true});
	        this.fieldConfigs = {};
	        for(var fields = this.fields, i = 0, size = fields.length; i < size; i++){
	        	if(fields[i].hidden == undefined){
	        		fields[i].hidden = false;
	        	}
	        	if(fields[i].type == "date" && fields[i].format == undefined){
	        		fields[i].format = "yyyy-MM-dd";
	        	}
	        	
	        	if(fields[i].searchable){
	        		this.sample[fields[i].name] = undefined;	        		
	        		this.searchParamfields.push(fields[i]);
	        	}
	        	
	        	this.fieldConfigs[fields[i].name] = fields[i];	        		
	        }
	       	        
			this.searchField.valueChanged(function(oldField,newField) {
		       <#-- clear old sample value -->
		       if(oldField){
		       		this.sample[oldField] = undefined;
		       		$("."+oldField).val(undefined);		       		
		       }
		    }.bind(this));
                                
            this._selectedAll = ko.observable(false); 
            this._selectedAll.valueChanged(function(oldVal,newVal) {        			            	
				ko.utils.arrayForEach(this.records(), function(el, index) {
				   	el._selected(newVal);
				   	//console.log("allowUpdate",this.allowUpdate);
				   	if(this.allowUpdate){
				   		if(newVal){
				   		
				   		}else{
				   		
				   		}
				   	}
				}.bind(this));
            }.bind(this));
            <#-- dynamic hide/show search fields 
            $("form .search-field-cap").css("display","none");            
		    this.searchFieldChanged  = function(self,event){
            	console.log(self.searchField()); 	
            	$("form .search-field-cap").css("display","none");
            	$("form ." + self.searchField()).css("display","inline");            		     
            };
            -->
		   
			
			<#-- set the background color according to record status -->			
	        this.tableRowStyle = function(elements, data) {
	            if(typeof params.tableRowStyle == "function"){
	            	$(elements).filter("tr").css(params.tableRowStyle.call(this,data));
	            }	            
	        }.bind(this); 
	        
	        <#-- set table row event -->
	        if(typeof params.tableRowEvent == "function"){
	        	this.tableRowEvent = params.tableRowEvent;
	        }else{
	        	this.tableRowEvent = function(data){};
	        }
	        
	        <#-- sorting 
	        this.sortByName = function() {
		        this.records.sort(function(a, b) {
		            return a.id < b.id ? -1 : 1;
		        });
		    };-->
	       
	        <#-- format the cell content -->
	        this.format = function(field,data){
	        	//console.log("data",data);
	        	var value = data[field];
	        	if(value == undefined || value == ""){
	        		return "";
	        	}
	        	
	        	var config = this.fieldConfigs[field];
	        	if(typeof config.format == "function"){
	        		value = config.format.call(this,config,data);
	        	}else if(config.type == "date"){
	        		if(typeof value.Format == "function"){
	        			value = value.Format(field.format);
	        		}
	        	}else if(config.type == "number"){
	        		
	        	}else if(config.type == "select"){	        		
					for(var i = 0, size = config.options.length; i < size; i++){
						if(config.options[i].value == value){
							value = config.options[i].label;
							break;
						} 
					}
	        	}
	        		        	
	        	return value;	        	
	        }.bind(this);
	        
	        <#-- hide/show row selector 			
			 $("table#" + self.tableId +"  .selector").css("display",this.selector?"block":"none");
			-->
				
			<#-- load the data async -->	
            this.searchRecord = function(self,event){
            	this.message("");
				this.showMessage(false);
                //console.log("sample",self.sample,"searchField",self.searchField());                
                <#-- get new records by sample-->
                <#-- 
                $.getJSON(params.dataUrl, self.sample, function(result) {                
                	var data = result.data; //console.log("data",data);                	
					if(data && data.length > 0){
						for(var i = 0, size = data.length; i < size; i++){
							data[i]["_selected"] = ko.observable(false); 
							self.records.push(data[i]);			
						}									
					}					
					$("table#" + self.tableId +" tr.no-records-found").css("display",self.records().length == 0?"":"none");	
				});	
				-->
				
				//console.log("dataUrlSearch=",params.dataUrlSearch);
				if(params.dataUrlSearch == undefined){
					return;
				}
				<#-- clear the current records-->
                self.records.splice(0,self.records().length);
                
                //console.log("****POST******",  JSON.stringify({sample:self.sample,page:self.page() - 1,limit:self.limit()}));
                
				$.post({
					url: params.dataUrlSearch
					,data: JSON.stringify(self.sample) 
					,dataType:"json",cache:false ,contentType:"application/json"					
					,success:function(result,status){
						//console.log("*****result",result);							
						var data = result.data; 
						//console.log("*****data",data);                	
						if(data && data.length > 0){
							for(var i = 0, size = data.length; i < size; i++){
								data[i]["_selected"] = ko.observable(false); 
								self.records.push(data[i]);			
							}
						}		
						self.count(result.count);	
						$("table#" + self.tableId +" tr.no-records-found").css("display",self.records().length == 0?"":"none");	
					}
					,error:function(status, error){
						console.log("###update records",data,status);
					}
				});
				 
				<#--uncheck selectAll checkbox -->	 
				$("#_selectAllCheckbox").attr({checked: false});  
				self._selectedAll(false);				
            };			
            
            <#-- create a new record -->
            this.createRecord = function(self,event){
            	this.message("");
				this.showMessage(false);
				
 				 var record = {_selected: ko.observable(true)};
 				 for(var fields = self.fields, i = 0, size = fields.length; i < size; i++){		        	
		        			        	
		        	var defaultValue = fields[i].defaultValue;
		        	if(typeof defaultValue == "function"){
		        		defaultValue = fields[i].defaultValue(); 
		        	}
		        	       	
		        	if(defaultValue && fields[i].type == "date"){
        				defaultValue = defaultValue.Format(fields[i].format);
        			}
		        	record[fields[i].name] = defaultValue;		        	
		         }
		         //console.log("***add new record***",record);
		         self.records.push(record);	
            }; 
            <#-- delete all selected records -->
            this.deleteRecord = function(self,event){
            	var deletedIds = [], selected = false;
				var data = self.records();    
				for(var i = data.length -1 ; i >= 0; i--){
					if(data[i]["_selected"]()){
						selected = true;
						if(data[i].id){
							<#--add the id of record to delete -->
					    	deletedIds.push(data[i].id);
					    	self.records.splice(i,1);
					    }else{
					    	<#--remove new records directly -->
					    	self.records.splice(i,1);
					    }
					}							
				}	
				if(!selected){
					this.message("请选择需要删除的记录");
					this.showMessage(true);
				}	
				<#-- console.log("deleteRecord****",$.param({ids: deletedIds},true));-->	
				if(deletedIds.length == 0){					
					return;
				}
				
				<#--remove records from server -->
				if(params.dataUrlDelete == undefined){
					return;
				}
				$.post({
					url: params.dataUrlDelete
					,data: JSON.stringify(deletedIds)
					,dataType:"json"
					,cache:false
					,contentType:"application/json"
					,error:function(status, error){
						console.log("###update records",data,status);
						self.message("删除失败");
						self.showMessage(true);
					}
					,success:function(data,status){		
						self.message("删除成功");
						self.showMessage(true);
						<#--remove records from page 				
						 var data = self.records(); 
						 for(var i = data.length -1 ; i >= 0; i--){
							if(data[i]["_selected"]()){
								if(i > 0){					
									self.records.splice(i,1);
								}else if(i === 0){
									self.records.shift();
								}
							}							
						}	
						-->
					}
				});				
            };
            
            this.saveRecord = function(self,event){            	
				var selected = ko.utils.arrayFilter(self.records(), function(el, index) {					
				    return el._selected(); 
				});
				
				//console.log("selected records",ko.toJS(selected));
				if(selected.length == 0){
					self.message("请选择要保存的记录");
					self.showMessage(true);
					return;
				}
								
				<#-- update records 
				var updatedRecords = ko.utils.arrayFilter(self.records(), function(el, index) {					
				    return el._selected() && el.id != undefined; 
				});				
				$.post({
					url: params.dataUrlUpdate
					,data: JSON.stringify(updatedRecords)
					,dataType:"json" ,cache:false	,contentType:"application/json"
					,error:function(status, error){
						console.log("###update records",data,status);
					}
					,success:function(result,status){
						var data = result.data;
						for(var records = self.records(), i = records.length-1; i >= 0; i--){
							if(records[i]._selected() && records[i].id){
								for(var k = data.length - 1; k >= 0; k--){
									if(records[i].id == data[k].id){
										data[k]["_selected"] = ko.observable(true);
										self.records.splice(i,1,data[k]);	
										data.splice(k,1);	
									}	
								}	
							}
						}						
					}
				});
				-->
				<#-- new records 
				var newRecords = ko.utils.arrayFilter(self.records(), function(el, index) {					
				    return el._selected() && el.id == undefined; 
				});
				$.post({
					url: params.dataUrlCreate
					,data: JSON.stringify(newRecords)
					,dataType:"json" ,cache:false	,contentType:"application/json"
					,error:function(status, error){
						console.log("###update records",data,status);
					}
					,success:function(result,status){
						var data = result.data;
						for(var records = self.records(), i = records.length-1; i >= 0; i--){
							if(records[i]._selected() && records[i].id == undefined){
								self.records.splice(i,1);
							}
						}
						
						if(data && data.length > 0){
							for(var i = 0, size = data.length; i < size; i++){
								data[i]["_selected"] = ko.observable(true); 
								self.records.push(data[i]);			
							}									
						}						
					}
				});	
				-->
				if(params.dataUrlSave == undefined){
					return;
				}
				$.post({
					url: params.dataUrlSave
					,data: JSON.stringify(selected)
					,dataType:"json"
					,cache:false
					,contentType:"application/json"
					,error:function(status, error){						 
						console.log("###update records",data,status);
						self.message("保存失败");
						self.showMessage(true);						
					}
					,success:function(result,status){
						self.message("保存成功");
						self.showMessage(true);	
						
						var data = result.data;
						<#-- replace selected records-->
						for(var records = self.records(), i = records.length-1; i >= 0; i--){
							if(records[i]._selected()){
								if(records[i].id){
									for(var k = data.length - 1; k >= 0; k--){
										if(records[i].id == data[k].id){
											data[k]["_selected"] = ko.observable(true);
											self.records.splice(i,1,data[k]);	
											data.splice(k,1);	
										}	
									}	
								}else{
									self.records.splice(i,1);
								}
							}
						}
						<#-- add new/updated records-->			
						if(data && data.length > 0){
							for(var i = 0, size = data.length; i < size; i++){
								data[i]["_selected"] = ko.observable(true); 
								self.records.push(data[i]);			
							}									
						}
					}
				});
			  
            };
			<#-- 		
			$("td.selector input:checkbox:checked").each(function(index,item){
				console.log("selected",item);
			});	
			 
			 $(".remove").click(function () {
			    viewModel.items.remove(ko.dataFor(this));
			});
			 -->			 			
		}
	});
</#macro>
